This is a documented WhiteCap 'config' file designed to explain WhiteCap configs in the hopes that you can make you own. In fact, most of the configs WhiteCap users have sent in. If you make your own configs and they turn out well, please send me them--I'll include what you send in a cool configs folder when i release the next version of WhiteCap (my email: aco5@cornell.edu). Check out other config files to see how the various parameters can be used in different ways. To make things easier, I put the stuff seen by WhiteCap in boldface type (ie. not the comments like these I'm typing in now--there's two ways to make comments). This is ok, because SimpleText puts style data in the resource fork, not the data fork (so WhiteCap just gets the text data). As you read through this, don't get discouraged--there's a *lot* of stuff here, so be patient.
If you see something is quotes, that paramater either expects a number or an expression, and I'll say which. If it's labeled an expression, you can do all the things described below as well as reference various other global values (A, B, C, D vars, dt, st, t, and mag()--all explained later). When you see a parameter not in quotes, it means that you can only put an integer value there (ex, 4, -55, 4343--nothing but digits and a leading dash if it's negative). Also, be sure you don't forget key things like commas, quotes, etc. Parameters are assumed to be 0 or "0" (depending on the type) if they are omitted from a config file. Finally, it doesn't matter what order parameters appear.
Many parameters in a WhiteCap config file ask for 'expressions'. Expressions are functions--they represent a single value that depends on an algebraic combonation of constants, and variables through operators and functions. "3*b", "3.141", "sqrt(t+7)", and "(s+t+2.7)^dt" are all examples of expressions. In WhiteCap expressions, all letters are case insensitive, and there are the following functions: sin(), cos(), tan(), atan(), sqrt(), sqr(), log(), exp(), tan(), abs(), and...
pos(x) == x when x >= 0 and 0 when x < 0.
sgn(x) == 1 when x >= 0 and -1 when x < 0
clip(x) == 0 when x < 0, 1 when x > 1, and x when 0 < x < 1
trnc(x) == [x] (ie, the decimal portion is stripped)
rnd(x) returns a random (float) value from 0 to x (inclusive)
seed(x) seeds the random number generator to x, returns x
sqwv(x) == 1 if |x| <= 1.0 and 0 otherwise.
trwv(x) == |x| if |x| < 1 and trwv( |x| - 2 ) otherwise.
Operators are used to combine two values in expressions, and the operators available in WhiteCap are: +,-,*,/,%,^ (% is the mod operator and the a^b is a raised to the b power). Traditional order of operations apply and you may freely use parentheses. */
/* Resolution: When a sample is taken, another won't be taken until a certain period of time later. The following time (in milliseconds) is this length of time. The higher this delay is, the less often "samples" will be taken and thus the trail will appear more sparse. If you have a config where samples seem to be really crowded, raise this value by 30 or 40. */
Resn=10,
/* Duration: This specifies how long a sample sticks around until its considered expired. When a sample has been around longer than this time, it's deleted. So as this number increases, the more samples that will around each frame. This value is a number and is not an expression (where you can put in variable terms, etc).*/
Durn="1.3",
/* Camera position: Express the position of the camera. The variable "t" is available for all the camera expressions. t is the system time (in seconds), and is the way to get the camera to do things though time (change position or change viewing orientation) . CamX, Y, and X are the camera's coordinates in space. */
CamX="60 * sin( .5 * t )",
CamY="20 * cos( .3 * t )",
CamZ="14 + 6 * cos( .3 * t )",
/* Camera Look Point: Expresses the point in space the camera looks at. Hence the direction the camera looks is (-(CamX-CmLX),-(CamY-CmLY),-(CamZ-CmLZ)). */
CmLX="20",
CmLY="0",
CmLZ="0",
/* Camera 'Up' Direction: The direction of the following vector specifies the direction from the camera location that is 'up'--that is, it's the y direction in the camera's coordinate system. In other words, the segment from point CmL to point (CmL+CUp) goes from exact middle of the screen and points perfectly upward. Make sure this vector never crosses the precise direction as the Camera direction or else you'll cause an unsightly jump-discontinuity of camera up direction (as WhiteCap will be forced to choose an arbitrary 'up' direction). For example, as the camera's line of sight approaches the direction of CUp, the segment described above approaches a single pixel (in the middle of the screen). "Tunnel Vision" and "Canyon Chase" use CUp to make the camera change orientation in a cool way. */
CUpX="0",
CUpY="0",
CUpZ="1",
/* If you didn't catch all that Camera stuff the first time around, don't sweat it. If you look a enough configs you'll see how do mimic some basic camera movement. */
/* Tail Position/Shape: WhiteCap gives you access to 3 values and a function and needs back an xyz coordinate. The 3 values are: t--the system time index (in seconds), st--the system time the current sample was recorded, and s--a parametric value that goes from 0 to 1. The sound magnitude/amplitude of the current sample is accessed via the mag() function. mag( f ) returns the power of frequency f of the current sample, and the domain of mag() is 0 to 1 inclusive. WhiteCap also computes a commonly used value for you, dt--0 means the current sample was just recorded and 1 means it's about about to expire.
The next thing to learn is how to use temporary variables. WhiteCap allows you to compute commonly used values so that you can avoid having WhiteCap recompute things unnecessarily. For now, just know that A0, B0, B1, C1, etc, are temporary variables. Let's break WhiteCap down:
begin {
evaluate A0, A1, A2...
for each frame {
record a sound sample (ie, capture a freq spectrum for that moment in time)
erase recorded samples older than Durn
t = system time
evaluate B0, B1, B2...
evaluate and apply BckRGB (the background color)
evaluate CamXYZ, CmLXYZ, and CUpXYZ (the cam pos and orientation)
for sample = step thru samples {
st = sample.timeRecorded
dt = ( theTimeNow - sample.timeRecorded ) / Durn
setPenWidth( LWdt )
evaluate C0, C1, C2...
for s = 0 to 1 {
evaluate D0, D1, D2...
screen_pt = getScrnPosOf( X, Y, Z, CamXYZ, CmLXYZ, CUpXYZ )
if ( st == t )
setPenColor( LvlR, LvlG, LvlB )
else
setPenColor( R, G, B )
draw( screen_pt )
}
}
}
}
Using temporary variables is useful when you want to compute something once and use it multiple times (to avoid redundant computation). There are 4 groups of temporary variables available for use in WhiteCap: A, B, C and D. The A variables are evaluated once, when the config is loaded, the B variables are evaluated at the start if each frame, the C variables are evaluated each sample (for each frame), and the D variables are evaluated for each change in 's' (for each sample for each frame). The A variables are usually used as global config values when the config loads. For example, you could set A0, A1, A2 to be a random values that get used together to form an RGB color that's used for the config, so that each time the config loads it's would be a different color. The B variables are useful for computing things that depend on 't', such as the B0 parameter in Cosine Classic. The C variables are useful for computing things that depend on 'dt', that is, values that stay constant over s. For example, in this config we precompute a cosine in C0 because the cosine doesn't change with any change to s. D variables are useful for computing a value that's used multiple times and is dependent on s. The D variables are useful for computing values shared by the 6 expressions: X, Y, Z, R, G, B. For example, if the RGB all depend on some big function of s, it makes sense to do all the shared computation in D0 and just use D0 in R, G, and B.
The way you denote declare a temporary variable is by counting up from zero, such as A0, A1, A2, etc. Most included configs make extensive use of temporary variables.
Back to the WhiteCap main loop... Note how using the mag() function in an A or B variable wouldn't make any sense because they are values that constant for all the samples. There is one exception--if you use the mag() fcn inside a B var, it accesses the most recent sample (ie, dt == 0). This allows you set values (ie. B vars) that are universal for the entire frame. This is how could, say, make the background color beat with the music or make the camera jiggle with the bass beat. */
/* Until you get a feel for how to use temp variables, don't use them--just put everything in terms of t, st, dt, and/or s in the RGB and XYZ expressions. The only consequence will be that your config will run slow as WhiteCap evaluates those 6 expressions for each bin for each sample for each frame. Send me your config and I'll can show you how to make it faster. */
/* This is an oscillator than goes from -1.2 to .6, the 'wing' angle (in radians). Try taking changing the coefficient of dt or t to zero and observe the effects. */
/* We need the following value twice, and it depends on s, so we can't make it any faster than a D var. Note how we access the sound level/magnitude. */
D0="13 * abs( mag( s ) )",
/* If you want to check out XYZ expressions less complicated than this, check out "My Malia" */
/* Tail Color: This express the RGB for each point on the tail. The rules for the RGB expressions are the same as the XYZ expressions, and you're free to use temporary variables (although there's no need to use any in this example). The following three parameters express the the RGB of the point (X, Y, and Z). A value of 1.0 signifies 100% of a component, 0.0 represents a complete absence of that component. Check out the pseudocode for WhiteCap above to see when these three expressions are evaluated. Again, check out "My Malia" to see a less complicated RGB set. */
/* Note that I didn't bother to put the expr for R in a C variable. This is because when whitecap goes to evaluate an expression for each change in s, it won't bother to revaluate an expression if it doesn't have an s or D variable in it. It's always critical that you always move whatever you can into C expressions--that's what's gonna make the key speed difference for your config. */
/* "Level" Color (the color of the "present" sample, the sample where st == t). This is the color painted on the front end of the tail. If these params are missing, the RGB of the front of the wave is determined by above RGB expressions. These are expressions, so you're free to access t, s, and mag(). */
LvlR=".4",
LvlG=".4",
LvlB="1",
/* Background Color -- same param types as the Level color: Expressions that return a value from 0 to 1. You are free to access t, s, and mag() */
BckR="0",
BckG="0",
BckB="0",
/* Connecting Lines: A 1 here tells WhiteCap to connect adjacent samples together with lines, 0 means you don't want those lines. Try changing this to 0 and see what happens. */
ConL=1,
/* Set ConB to 1 if you want the points of the sample ("bins") to be connected. Set ConB to 0 if you don't want those lines. "Vortex" has the effect of 'particles' by setting ConL and ConB both equal to 0. If ConB is set to 2, WhiteCap draws as if it was set to 1 and draws a line from bin 0 to bin N. */
ConB=1,
/* Line Width: This is an expression of the pen width, in pixels, evaluated for each sample. You're free to access t, dt, st, and mag() here. */
LWdt="1",
/* Falloff: This number describes how "sticky" the magnitude levels are... Imagine a needle that moves to the volume of a song. Falloff is how fast the needle falls back to zero if you were to suddenly turn off the music. The higher this is, the faster the needle falls back to zero. Be careful, if you set it too close to zero, the level will too sticky and it will never change! Note if you set this above around .06, the level pretty much falls off instantly. */
Fall=".05",
/* Gaussian Blur: Blrs represents how steps of blurs you want in the tail. For example, if Blrs=3 then after WhiteCap will blur the last 1/3 of the tail, then the last 2/3 of the tail, then the entire tail. BlrB is the blur "box" size. It's how much things are blurred. BlrB set to less than 2 doesn't blur at all. You tell WhiteCap you don't want any blurring of any kind by setting Blrs to 0. */
Blrs=0,BlrB=3,
/* The height and width window this config fit into. WhiteCap uses these two params to shrink or expand your config based on the current window size. WhiteCap will always shrink your config, based on these values, such that *both* dimensions will fit in the window. For example, with the below values, and with a current window size of 100 wide and 400 tall, WhiteCap will shrink your config by 1/5 at all times. */
widt=500,heig=450,
/* Scale: Directly scales the screen x and y coordinates. This param basically provides an easy way to shrink/expand your config painlessly. Note: doubling widh and heig will have exactly the same effect as halving Scal. */
Scal="500",
/* Scale with size: When this is 1, WhiteCap will scale your config so that it will fit nicely inside the current window. If this param is 0, WhiteCap will not scale your config in the way described in the descripion for widh and heig if it means your config will be made larger. Usually this is set to 1, but in Flame, for example, where blurring is used, WhiteCap would slow to a crawl if scaled Flame up to a particularly large window. */
ScSz=1,
/* Perspective Scale: How much points obscure to the fringes based on their distance from the camera. WhiteCap uses the following formula to express screen coords:
scrn_x = Scal * scrn_x / ( scrn_z + Pers )
The bigger you make this value, the more 'dimensionless' things will look. For example, the camera that records from the backside of the pitcher in a major league baseball game has a high Pers value because the camera is very far away. On the other hand, if you stand at the bottom of a skyscraper, your Pers is really low because your eyes are very near the object, causing high perspective-distortion for near features. */
Pers="150",
/* This should always equal to the lowest version of WhiteCap the config is compatible with (times 10). WhiteCap makes sure the config it's about to show matches it's current version. If it doesn't match, WhiteCap will just display the built-in 'factory' config (it's green with a red level line). */